/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package towerz.game.entity;

import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import towerz.game.Sprite;
import towerz.system.StateManager;
import towerz.system.Utilities;
import towerz.system.xml.XmlNode;

/**
 *
 * @author LegACy
 */
public class Enemy extends Entity{
	//Direction enum
	public static final int DIRECTION_DOWN	= 0;
	public static final int DIRECTION_LEFT	= 1;
	public static final int DIRECTION_UP	= 2;
	public static final int DIRECTION_RIGHT = 3;

	protected Enemy() {
		//Initialize
		m_Gold			= 0;
		m_Goal			= 0;
		m_TileX			= 0;
		m_TileY			= 0;
		m_OffsetX		= 0;
		m_OffsetY		= 0;
		m_Velocity		= 0;
		m_Direction		= 0;
		m_HealthMax		= 1;
		m_Health		= 1;
		m_SpeedModifier	= 1.0f;
		m_ArmorModifier	= 1.0f;
		m_BuffList		= new Vector();
        m_DeletedBuffList   = new Vector();

		//No array
		m_PathX		= null;
		m_PathY		= null;
		m_Sprites	= null;
	}

	public Enemy(XmlNode xml, Image[][][] images, int[] pathX, int[] pathY, int x, int y) {
		//Initialize
		this();

		//Initialize data
		m_TileX	= x;
		m_TileY	= y;
		m_PathX = pathX;
		m_PathY = pathY;

		//Get direction
		calculateDirection();

		//Prepare variable
		int Delay			= -1;

		//For each node
		for(int i=0; i < xml.getChildren().size(); ++i) {
			//Get tag name and it's value
			String Tag		= ((XmlNode)xml.getChildren().elementAt(i)).getNodeName();
			String Value	= ((XmlNode)((XmlNode) xml.getChildren().elementAt(i)).getChildren().elementAt(0)).getNodeValue();

			//Save data
			if(Tag.equals("gold"))				m_Gold = Integer.parseInt(Value);
			else if (Tag.equals("animation"))	Delay = Integer.parseInt(Value);
			else if (Tag.equals("velocity"))	m_Velocity = Integer.parseInt(Value);
			else if (Tag.equals("health")) {
                m_HealthMax = Integer.parseInt(Value);
                m_Health    = m_HealthMax;
			}
		}

		//Create sprite
		if (Delay >= 0) {
			m_Sprites = new Sprite[4];
			for (int i = 0; i < m_Sprites.length; i++)
				m_Sprites[i] = new Sprite(images[i], 0, 0, Delay);
		}
	}

	public int getX()		{	return (m_TileX * Utilities.TILE_WIDTH)  + (int)m_OffsetX;	}
    public int getY()		{	return (m_TileY * Utilities.TILE_HEIGHT) + (int)m_OffsetY;	}
	public int getGold()	{	return m_Gold;												}
	public int getHealth()	{	return m_Health;											}

	protected final void calculateDirection() {
		//Get direction
		if (m_PathY[m_Goal] < m_TileY)		m_Direction = Enemy.DIRECTION_UP;
		else if (m_PathY[m_Goal] > m_TileY)	m_Direction = Enemy.DIRECTION_DOWN;
		else if (m_PathX[m_Goal] < m_TileX)	m_Direction = Enemy.DIRECTION_LEFT;
		else if (m_PathX[m_Goal] > m_TileX)	m_Direction = Enemy.DIRECTION_RIGHT;
	}

	public void damage(int damage, Buff buff) {
		//Reduce health
		m_Health -= damage;
		for (int i = 0; i < m_Sprites.length; i++) m_Sprites[i].addTint(1, 200);

		//Add buff if not null
		if (buff != null) addBuff(buff);
	}

	protected void addBuff(Buff buff) {
		//Check does it exist?
		int i = 0;
		Buff OldBuff = null;
		while (OldBuff == null && i < m_BuffList.size()) {
			//Check
			if (((Buff)m_BuffList.elementAt(i)).getIndex() == buff.getIndex()) OldBuff = (Buff)m_BuffList.elementAt(i);
            
			//Next
			i++;
		}

		//Remove old buff
		if (OldBuff != null) removeBuff(OldBuff);

		//Add the buff
		m_BuffList.addElement(buff);
		for (int j = 0; j < m_Sprites.length; ++j) m_Sprites[j].addTint(buff.getTint(), buff.getDuration());
	}

	protected void removeBuff(Buff buff) {
		//Remove buff
        m_BuffList.removeElement(buff);

        //m_DeletedBuffList.addElement(buff);
	}
	
	public void strengthen(int number) {
		//Nothing if 0
		if (number <= 0) return;
		
		//Increase
		for (int i = 0; i < number; i++) m_HealthMax *= 1.5f;
		m_Health = m_HealthMax;
	}

	public void update(long time) {
		//Check buff
		checkBuff(time);

		//Update sprites
		for (int i = 0; i < m_Sprites.length; i++) m_Sprites[i].update(time);

		//Skip if no goal
		if (m_Goal < 0) return;

		//Move based on direction
		float Offset = m_Velocity * m_SpeedModifier * time / 1000.0f;
		if (m_Direction == Enemy.DIRECTION_DOWN)		m_OffsetY += Offset;
		else if (m_Direction == Enemy.DIRECTION_UP)		m_OffsetY -= Offset;
		else if (m_Direction == Enemy.DIRECTION_LEFT)	m_OffsetX -= Offset;
		else if (m_Direction == Enemy.DIRECTION_RIGHT)	m_OffsetX += Offset;

		//Update tile
		while (m_OffsetX >=  Utilities.TILE_WIDTH)	{	m_OffsetX -= Utilities.TILE_WIDTH;  m_TileX++;	}
		while (m_OffsetX <= -Utilities.TILE_WIDTH)	{	m_OffsetX += Utilities.TILE_WIDTH;  m_TileX--;	}
		while (m_OffsetY >=  Utilities.TILE_HEIGHT)	{	m_OffsetY -= Utilities.TILE_HEIGHT; m_TileY++;	}
		while (m_OffsetY <= -Utilities.TILE_HEIGHT)	{	m_OffsetY += Utilities.TILE_HEIGHT; m_TileY--;	}

		//Check, has goal reached?
		if (m_TileX == m_PathX[m_Goal] && m_TileY == m_PathY[m_Goal]) {
			//Reset offset
			m_OffsetX = 0;
			m_OffsetY = 0;

			//Next goal
			m_Goal++;
			if (m_Goal >= m_PathX.length)	m_Goal = -1;
			else							calculateDirection();
		}
    }

	protected void checkBuff(long time) {
		//Reset modifier
		m_ArmorModifier	= 1.0f;
		m_SpeedModifier = 1.0f;

		//For each buff
		for (int i = 0; i < m_BuffList.size(); i++) {
			//Update
			((Buff)m_BuffList.elementAt(i)).update(time, this);
			m_ArmorModifier *= ((Buff)m_BuffList.elementAt(i)).getModifier(Buff.ARMOR_MODIFIER);
			m_SpeedModifier *= ((Buff)m_BuffList.elementAt(i)).getModifier(Buff.SPEED_MODIFIER);

			//Check dead buff
			if (!((Buff)m_BuffList.elementAt(i)).isActive()) m_DeletedBuffList.addElement(m_BuffList.elementAt(i));
		}

		//Delete inactive buffs
		for (int i = 0; i < m_DeletedBuffList.size(); i++) removeBuff((Buff) m_BuffList.elementAt(i));
		m_DeletedBuffList.removeAllElements();
	}

	public void draw(Graphics g, int startX, int startY, int endX, int endY, int offsetX, int offsetY) {
		//Skip if there's no image
		if (m_Sprites == null) return;

		//Get current sprite
		Sprite Current = m_Sprites[m_Direction];

		//Get rect
		int Left	= ((m_TileX - startX) * Utilities.TILE_WIDTH)  + (int)m_OffsetX + offsetX + ((Utilities.TILE_WIDTH - Current.getWidth()) / 2);
		int Top		= ((m_TileY - startY) * Utilities.TILE_HEIGHT) + (int)m_OffsetY + offsetY - Current.getHeight() + (int)(Utilities.TILE_HEIGHT * 0.75f);

		//Ensure in drawing area
		if (Left + Current.getWidth() < 0)					return;
		else if(Left > StateManager.instance().getWidth())	return;
		else if (Top + Current.getHeight() < 0)				return;
		else if (Top > StateManager.instance().getHeight())	return;

		//Draw health bar
        g.setColor(0x0040FF00);
        g.fillRect(Left + 4, Top - 6, (int)((float)m_Health / (float)m_HealthMax * (float)(Current.getWidth() - 8)), 4);

		//Draw sprite
		m_Sprites[m_Direction].setPosition(Left, Top);
		m_Sprites[m_Direction].draw(g);
	}

	//Data
	protected int		m_Gold;
	protected int		m_Health;
    protected int		m_HealthMax;
	protected int		m_Direction;
	protected float		m_Velocity;
	protected float		m_SpeedModifier;
	protected float		m_ArmorModifier;
	protected Vector	m_BuffList;
    protected Vector	m_DeletedBuffList;

	//Position
	protected float m_OffsetX;
	protected float m_OffsetY;

	//Movement
	protected int	m_Goal;
	protected int[]	m_PathX;
	protected int[]	m_PathY;

	//Images
	protected Sprite[] m_Sprites;
}
